#!/usr/bin/env python

from sqlalchemy.orm import scoped_session
from .exception import CustomException
from .utils import Utils
from .my_redis import MyRedis


def apply(**kwargs):
    def wapper(cls):
        for x in kwargs:
            setattr(cls, x, kwargs.get(x))
        return cls
    return wapper

def Singleton(cls):
    """ 单例 """
    _instance = {}

    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton


def Transaction(name=None):
    def wapper(func):
        def _deco(self, *args, **kwargs):
            if name is not None and hasattr(self, name):
                session = getattr(self, name)
                if isinstance(session, scoped_session):
                    try:
                        res = func(self, *args, **kwargs)
                        session.commit()
                        return res
                    except CustomException as ce:
                        session.rollback()
                        raise CustomException(code=ce.code, desc=ce.msg)
                    except Exception as e:
                        session.rollback()
                        raise e
                    finally:
                        pass
            else:
                print("找不到session对象，无法开启自动事务")

        return _deco

    return wapper


def Cache(name='redis', time=3000):
    """缓存"""
    def outer(func):
        def _deco(self, *args, **kwargs):
            cache_key = Utils._compute_key(func, args, kwargs)
            if hasattr(self, name):
                cache_obj = getattr(self, name, None)
                if isinstance(cache_obj, MyRedis):
                    data = cache_obj.get(cache_key)
                    if data is None:
                        print("没有命中缓存,执行函数")
                        data = func(self, *args, **kwargs)
                        print("将数据加入到缓存中")
                        cache_obj.setex(cache_key, time, data)
                    else:
                        print("命中缓存")
                else:
                    data = func(self, *args, **kwargs)
            else:
                data = func(self, *args, **kwargs)

            return data

        return _deco

    return outer
